package repository

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/promotion/model"

	"github.com/sirupsen/logrus"
	"github.com/volatiletech/null/v8"
	"github.com/volatiletech/sqlboiler/v4/boil"
	"github.com/volatiletech/sqlboiler/v4/queries/qm"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/cache"
)

type (
	// ActivityRepository is an interface to be customized, add more methods here,
	// and implement the added methods in customActivityRepository.
	ActivityRepository interface {
		FindOne(ctx context.Context, id uint64) (*model.PromotionActivity, error)
		FindOneByName(ctx context.Context, name string) (*model.PromotionActivity, error)
		FindOneWithExpire(
			ctx context.Context,
			id uint64,
			expire time.Duration,
		) (*model.PromotionActivity, error)
		FindOneNoCache(
			ctx context.Context,
			conn boil.ContextExecutor,
			id uint64,
		) (*model.PromotionActivity, error)
		GetList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivity, int64, error) // ##25.04.24##
		Insert(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.PromotionActivity,
			rel *model.PromotionActivityRel,
		) error // ##25.04.24##
		Update(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.PromotionActivity,
			rel *model.PromotionActivityRel,
		) error
		UpdateBatch(ctx context.Context, tx boil.ContextExecutor, ids []uint64, cols model.M) error
		SoftDelete(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		Restore(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		ForceDelete(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		ForceDeleteBatch(ctx context.Context, tx boil.ContextExecutor, ids []uint64) error
		GetRuleGroupList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionRuleGroup, int64, error)
		GetRuleList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionRule, int64, error)
		GetProductList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivityProductRelationship, int64, error) // ##25.05.14##
		GetProductBrandList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivityProductBrandRelationship, int64, error) // ##25.05.13##
		GetProductCategoryList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivityProductCategoryRelationship, int64, error) // ##25.05.13##
		GetCouponList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivityCouponRelationship, int64, error)
		GetLogList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivityLog, int64, error)
		UpdateBindRel(
			ctx context.Context,
			tx boil.ContextExecutor,
			id uint64,
			rel *model.PromotionActivityBindRel,
		) error

		SyncQiniu(ctx context.Context, id uint64, mediaId uint64, url string) (int64, error) // ##25.03.02##
		GetMedia(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionAttachmentRelationship, int64, error) // ##25.04.25##
		GetMeta(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.PromotionActivityMetum, int64, error) // ##25.04.25##
	}

	customActivityRepository struct {
		modelx.CachedConn
		mysqlConn           *sql.DB
		cacheIdPrefix       string
		cacheNamePrefix     string
		cacheIdExpirePrefix string
	}
)

// NewActivityRepository returns a repository for the database table.
func NewActivityRepository(mysqlConn *sql.DB, cacheConf cache.CacheConf) ActivityRepository {
	return &customActivityRepository{
		CachedConn:          modelx.NewConn(mysqlConn, cacheConf),
		mysqlConn:           mysqlConn,
		cacheIdPrefix:       "cache:promotion:activities:id:",
		cacheNamePrefix:     "cache:promotion:activities:name:",
		cacheIdExpirePrefix: "cache:promotion:activities:id:expire:",
	}
}

func (r *customActivityRepository) FindOne(
	ctx context.Context,
	id uint64,
) (*model.PromotionActivity, error) {
	cacheIdKey := r.formatPrimary(id)
	var resp model.PromotionActivity
	err := r.QueryCtx(ctx, &resp, cacheIdKey, func(ctx context.Context, conn *sql.DB, v any) error {
		data, err := model.FindPromotionActivity(ctx, conn, id)
		if err != nil {
			return err
		}

		*v.(*model.PromotionActivity) = *data

		return nil
	})

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customActivityRepository) FindOneByName(
	ctx context.Context,
	name string,
) (*model.PromotionActivity, error) {
	cacheNameKey := r.formatNameKey(name)
	var resp model.PromotionActivity
	err := r.QueryRowIndexCtx(ctx, &resp, cacheNameKey, r.formatPrimary,
		func(ctx context.Context, conn *sql.DB, v any) (i any, e error) {
			mods := []qm.QueryMod{
				model.PromotionActivityWhere.Name.EQ(name),
			}
			list, err := model.PromotionActivities(mods...).All(ctx, conn)
			if err != nil {
				return nil, err
			}

			*v.(*model.PromotionActivity) = *list[0]

			return list[0].ID, nil
		}, r.queryPrimary)

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customActivityRepository) FindOneWithExpire(
	ctx context.Context,
	id uint64,
	expire time.Duration,
) (*model.PromotionActivity, error) {
	cacheIdKey := r.formatPrimary(id)
	var resp model.PromotionActivity
	err := r.QueryWithExpireCtx(ctx, &resp, cacheIdKey, expire, func(ctx context.Context, conn *sql.DB, v any) error {
		data, err := model.FindPromotionActivity(ctx, conn, id)
		if err != nil {
			return err
		}

		*v.(*model.PromotionActivity) = *data

		return nil
	})

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customActivityRepository) FindOneNoCache(
	ctx context.Context,
	conn boil.ContextExecutor,
	id uint64,
) (*model.PromotionActivity, error) {
	var db boil.ContextExecutor = r.mysqlConn
	if conn != nil {
		db = conn
	}
	data, err := model.FindPromotionActivity(ctx, db, id)
	logrus.Info(fmt.Sprintf("FindOneNoCache err: %+v", err))
	switch err {
	case nil:
		return data, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customActivityRepository) GetList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivity, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	var statistic bool
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityColumns.ID+" DESC"))
					mods = append(mods, model.PromotionActivityWhere.ID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityColumns.ID+" ASC"))
					mods = append(mods, model.PromotionActivityWhere.ID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		case "statistic":
			if val, ok := v.(string); ok && val == "1" { // 按 Status 统计
				statistic = true
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityColumns.ID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.ID, opMap)...)
		case model.PromotionActivityColumns.Name:
			mods = append(mods, modelx.GetStringMods(model.PromotionActivityColumns.Name, opMap)...)
		case model.PromotionActivityColumns.ActivityType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.ActivityType, opMap)...)
		case model.PromotionActivityColumns.MutexType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.MutexType, opMap)...)
		case model.PromotionActivityColumns.ScopeType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.ScopeType, opMap)...)
		case model.PromotionActivityColumns.TimesLimit:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.TimesLimit, opMap)...)
		case model.PromotionActivityColumns.GroupMode:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.GroupMode, opMap)...)
		case model.PromotionActivityColumns.GroupType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.GroupType, opMap)...)
		case model.PromotionActivityColumns.SeckillLimit:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.SeckillLimit, opMap)...)
		case model.PromotionActivityColumns.PackageType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.PackageType, opMap)...)
		case model.PromotionActivityColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityColumns.Status, opMap)...)
		case model.PromotionActivityColumns.StartedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityColumns.StartedAt, opMap)...)
		case model.PromotionActivityColumns.EndedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityColumns.EndedAt, opMap)...)
		}
	}

	if statistic {
		mods = append(mods, qm.Select(fmt.Sprintf(
			"%s, count(%s) as %s",
			model.PromotionActivityColumns.Status,
			model.PromotionActivityColumns.Status,
			model.PromotionActivityColumns.Sort,
		)))
		mods = append(mods, qm.GroupBy(model.PromotionActivityColumns.Status))
		preList, preErr := model.PromotionActivities(mods...).All(ctx, r.mysqlConn)
		if preErr != nil {
			err = preErr
			return
		}

		return preList, 0, nil
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivities(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.PromotionActivityColumns.ID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivities(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) Insert(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.PromotionActivity,
	rel *model.PromotionActivityRel,
) error {
	err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		err := data.Insert(ctx, db, boil.Infer())
		if err != nil {
			return err
		}

		if rel == nil {
			return nil
		}

		activityId := data.ID

		if len(rel.Meta) > 0 {
			for _, v := range rel.Meta {
				v.ActivityID = activityId
				err = v.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Media) > 0 {
			for _, v := range rel.Media {
				v.ObjectID = activityId
				v.ObjectType = uint16(globalkey.AttachmentLogTypePromotion)
				err = v.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Groups) > 0 {
			for _, groupRel := range rel.Groups {
				if groupRel.Group != nil {
					groupRel.Group.ActivityID = activityId
					err = groupRel.Group.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}

					if len(groupRel.Rules) > 0 {
						groupId := groupRel.Group.GroupID
						for _, rule := range groupRel.Rules {
							rule.ActivityID = activityId
							rule.GroupID = groupId
							err = rule.Insert(ctx, db, boil.Infer())
							if err != nil {
								return err
							}
						}
					}
				}
			}
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customActivityRepository) Update(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.PromotionActivity,
	rel *model.PromotionActivityRel,
) error {
	err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		blacklist := []string{
			model.PromotionActivityColumns.ID,
			model.PromotionActivityColumns.ActivityType,
			model.PromotionActivityColumns.DeletedAt,
		}
		if rel != nil && len(rel.Blacklist) > 0 {
			blacklist = append(blacklist, rel.Blacklist...)
		}
		rowsAff, err := data.Update(ctx, db, boil.Blacklist(blacklist...))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		if rel == nil {
			return nil
		}

		activityId := data.ID
		if len(rel.Groups) > 0 {
			for _, groupRel := range rel.Groups {
				if groupRel.Group != nil {
					if groupRel.Group.GroupID > 0 {
						rowsAff, err = groupRel.Group.Update(ctx, db, boil.Blacklist(
							model.PromotionRuleGroupColumns.GroupID,
							model.PromotionRuleGroupColumns.ActivityID,
							model.PromotionRuleGroupColumns.DeletedAt,
						))
						if err != nil {
							return err
						}

						if rowsAff == 0 {
							return model.ErrNotUpdated
						}
					} else {
						groupRel.Group.ActivityID = activityId
						err = groupRel.Group.Insert(ctx, db, boil.Infer())
						if err != nil {
							return err
						}
					}

					if len(groupRel.Rules) > 0 {
						groupId := groupRel.Group.GroupID
						for _, rule := range groupRel.Rules {
							if rule.RuleID > 0 {
								rowsAff, err = rule.Update(ctx, db, boil.Blacklist(
									model.PromotionRuleColumns.RuleID,
									model.PromotionRuleColumns.ActivityID,
									model.PromotionRuleColumns.GroupID,
									model.PromotionRuleColumns.DeletedAt,
								))
								if err != nil {
									return err
								}

								if rowsAff == 0 {
									return model.ErrNotUpdated
								}
							} else {
								rule.ActivityID = activityId
								rule.GroupID = groupId
								err = rule.Insert(ctx, db, boil.Infer())
								if err != nil {
									return err
								}
							}
						}
					}

					if len(groupRel.DelRuleIds) > 0 {
						var mods []qm.QueryMod
						mods = append(mods, model.PromotionRuleWhere.RuleID.IN(groupRel.DelRuleIds))
						_, err = model.PromotionRules(mods...).DeleteAll(ctx, db)
						if err != nil {
							return err
						}
					}
				}
			}
		}

		if len(rel.DelGroupIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.PromotionRuleGroupWhere.GroupID.IN(rel.DelGroupIds))
			_, err = model.PromotionRuleGroups(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}

		if len(rel.Meta) > 0 {
			for _, v := range rel.Meta {
				if v.MetaID > 0 {
					_, err = v.Update(ctx, db, boil.Blacklist(
						model.PromotionActivityMetumColumns.MetaID,
						model.PromotionActivityMetumColumns.ActivityID,
						model.PromotionActivityMetumColumns.MetaKey,
					))
					if err != nil {
						return err
					}
				} else {
					v.ActivityID = activityId
					err = v.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}
				}
			}
		}

		if len(rel.Media) > 0 {
			for _, v := range rel.Media {
				if v.AttachmentRelationshipID > 0 {
					_, err = v.Update(ctx, db, boil.Blacklist(
						model.PromotionAttachmentRelationshipColumns.AttachmentRelationshipID,
						model.PromotionAttachmentRelationshipColumns.ObjectID,
						model.PromotionAttachmentRelationshipColumns.ObjectType,
						model.PromotionAttachmentRelationshipColumns.AttachmentID,
					))
					if err != nil {
						return err
					}
				} else {
					v.ObjectID = activityId
					v.ObjectType = uint16(globalkey.AttachmentLogTypePromotion)
					err = v.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}
				}
			}
		}

		if len(rel.DelMetaIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.PromotionActivityMetumWhere.MetaID.IN(rel.DelMetaIds))
			_, err = model.PromotionActivityMeta(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}

		if len(rel.DelMediaIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.PromotionAttachmentRelationshipWhere.AttachmentRelationshipID.IN(rel.DelMediaIds))
			_, err = model.PromotionAttachmentRelationships(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customActivityRepository) UpdateBatch(
	ctx context.Context,
	tx boil.ContextExecutor,
	ids []uint64,
	cols model.M,
) error {
	if len(ids) > 0 {
		err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
			var db boil.ContextExecutor
			if tx != nil {
				db = tx
			} else {
				db = conn
			}

			var mods []qm.QueryMod
			mods = append(mods, model.PromotionActivityWhere.ID.IN(ids))

			rowsAff, err := model.PromotionActivities(mods...).UpdateAll(ctx, db, cols)
			if err != nil {
				return err
			}

			if rowsAff == 0 {
				return model.ErrNotUpdated
			}

			return nil
		}, r.formatPrimaries(ids)...)

		return err
	}

	return nil
}

func (r *customActivityRepository) SoftDelete(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	if data.Status == uint16(globalkey.StatusDeleted) {
		return nil
	}

	data.DelStatus = data.Status
	data.Status = uint16(globalkey.StatusDeleted)
	data.DeletedAt = null.TimeFrom(time.Now())

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.PromotionActivityColumns.ID,
			model.PromotionActivityColumns.UpdatedAt,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customActivityRepository) Restore(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	if data.Status != uint16(globalkey.StatusDeleted) {
		return nil
	}

	data.Status = data.DelStatus
	data.DeletedAt = null.TimeFromPtr(nil)

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.PromotionActivityColumns.ID,
			model.PromotionActivityColumns.UpdatedAt,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customActivityRepository) ForceDelete(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Delete(ctx, db)
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotDeleted
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customActivityRepository) ForceDeleteBatch(
	ctx context.Context,
	tx boil.ContextExecutor,
	ids []uint64,
) error {
	if len(ids) > 0 {
		err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
			var db boil.ContextExecutor
			if tx != nil {
				db = tx
			} else {
				db = conn
			}

			var mods []qm.QueryMod
			mods = append(mods, model.PromotionActivityWhere.ID.IN(ids))

			rowsAff, err := model.PromotionActivities(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}

			if rowsAff == 0 {
				return model.ErrNotDeleted
			}

			return nil
		}, r.formatPrimaries(ids)...)

		return err
	}

	return nil
}

func (r *customActivityRepository) getCacheKeys(data *model.PromotionActivity) []string {
	if data == nil {
		return []string{}
	}

	cacheIdKey := r.formatPrimary(data.ID)
	cacheNameKey := r.formatNameKey(data.Name)
	cacheKeys := []string{
		cacheIdKey,
		cacheNameKey,
	}

	return cacheKeys
}

func (r *customActivityRepository) formatPrimary(primary any) string {
	return fmt.Sprintf("%s%v", r.cacheIdPrefix, primary)
}

func (r *customActivityRepository) formatPrimaries(primaries []uint64) []string {
	var resp []string
	for _, primary := range primaries {
		resp = append(resp, r.formatPrimary(primary))
	}

	return resp
}

func (r *customActivityRepository) formatNameKey(name string) string {
	return fmt.Sprintf("%s%s", r.cacheNamePrefix, name)
}

func (r *customActivityRepository) queryPrimary(ctx context.Context, conn *sql.DB, v, primary any) error {
	var uid uint64
	if jsonId, ok := primary.(json.Number); ok {
		if int64Id, err := jsonId.Int64(); err == nil {
			uid = uint64(int64Id)
		} else {
			return err
		}
	}

	data, err := model.FindPromotionActivity(ctx, conn, uid)
	if err != nil {
		return err
	}

	*v.(*model.PromotionActivity) = *data

	return nil
}

func (r *customActivityRepository) GetRuleGroupList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionRuleGroup, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionRuleGroupColumns.GroupID+" DESC"))
					mods = append(mods, model.PromotionRuleGroupWhere.GroupID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionRuleGroupColumns.GroupID+" ASC"))
					mods = append(mods, model.PromotionRuleGroupWhere.GroupID.GT(val))
					previousCount = 1
				}
			}
		case "orderBy":
			if withCount != 3 && withCount != 4 {
				if val, ok := v.(string); ok && val != "" {
					mods = append(mods, qm.OrderBy(val))
				}
			}
		case "select":
			if val, ok := v.(string); ok && val != "" {
				selectCol = val
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionRuleGroupColumns.GroupID:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleGroupColumns.GroupID, opMap)...)
		case model.PromotionRuleGroupColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleGroupColumns.ActivityID, opMap)...)
		case model.PromotionRuleGroupColumns.Threshhold:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleGroupColumns.Threshhold, opMap)...)
		case model.PromotionRuleGroupColumns.Sort:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleGroupColumns.Sort, opMap)...)
		case model.PromotionRuleGroupColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleGroupColumns.Status, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionRuleGroups(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}

		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	} else {
		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	}

	var columns []string
	if selectCol != "" {
		if selectCol != "," {
			columns = strings.Split(selectCol, ",")
		} else {
			columns = append(columns, model.PromotionRuleGroupColumns.GroupID)
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionRuleGroups(mods...).All(ctx, r.mysqlConn)
	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetRuleList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionRule, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionRuleColumns.RuleID+" DESC"))
					mods = append(mods, model.PromotionRuleWhere.RuleID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionRuleColumns.RuleID+" ASC"))
					mods = append(mods, model.PromotionRuleWhere.RuleID.GT(val))
					previousCount = 1
				}
			}
		case "orderBy":
			if withCount != 3 && withCount != 4 {
				if val, ok := v.(string); ok && val != "" {
					mods = append(mods, qm.OrderBy(val))
				}
			}
		case "select":
			if val, ok := v.(string); ok && val != "" {
				selectCol = val
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionRuleColumns.RuleID:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.RuleID, opMap)...)
		case model.PromotionRuleColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.ActivityID, opMap)...)
		case model.PromotionRuleColumns.GroupID:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.GroupID, opMap)...)
		case model.PromotionRuleColumns.RuleType:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.RuleType, opMap)...)
		case model.PromotionRuleColumns.Mode:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.Mode, opMap)...)
		case model.PromotionRuleColumns.Value:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.Value, opMap)...)
		case model.PromotionRuleColumns.Sort:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.Sort, opMap)...)
		case model.PromotionRuleColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionRuleColumns.Status, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionRules(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}

		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	} else {
		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	}

	var columns []string
	if selectCol != "" {
		if selectCol != "," {
			columns = strings.Split(selectCol, ",")
		} else {
			columns = append(columns, model.PromotionRuleColumns.RuleID)
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionRules(mods...).All(ctx, r.mysqlConn)
	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetProductList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivityProductRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityProductRelationshipColumns.RelationshipID+" DESC"))
					mods = append(mods, model.PromotionActivityProductRelationshipWhere.RelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityProductRelationshipColumns.RelationshipID+" ASC"))
					mods = append(mods, model.PromotionActivityProductRelationshipWhere.RelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityProductRelationshipColumns.RelationshipID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.RelationshipID, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.ActivityID, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.ActivityType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.ActivityType, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.ProductType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.ProductType, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.ProductID, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.SkuID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.SkuID, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.Price:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.Price, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.Inventory:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.Inventory, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.Sort:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.Sort, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductRelationshipColumns.Status, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.CreatedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityProductRelationshipColumns.CreatedAt, opMap)...)
		case model.PromotionActivityProductRelationshipColumns.UpdatedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityProductRelationshipColumns.UpdatedAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivityProductRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.PromotionActivityProductRelationshipColumns.RelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivityProductRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetProductBrandList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivityProductBrandRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityProductBrandRelationshipColumns.RelationshipID+" DESC"))
					mods = append(mods, model.PromotionActivityProductBrandRelationshipWhere.RelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityProductBrandRelationshipColumns.RelationshipID+" ASC"))
					mods = append(mods, model.PromotionActivityProductBrandRelationshipWhere.RelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityProductBrandRelationshipColumns.RelationshipID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductBrandRelationshipColumns.RelationshipID, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductBrandRelationshipColumns.ActivityID, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.ActivityType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductBrandRelationshipColumns.ActivityType, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.ProductBrandID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductBrandRelationshipColumns.ProductBrandID, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.Sort:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductBrandRelationshipColumns.Sort, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductBrandRelationshipColumns.Status, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.CreatedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityProductBrandRelationshipColumns.CreatedAt, opMap)...)
		case model.PromotionActivityProductBrandRelationshipColumns.UpdatedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityProductBrandRelationshipColumns.UpdatedAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivityProductBrandRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.PromotionActivityProductBrandRelationshipColumns.RelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivityProductBrandRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetProductCategoryList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivityProductCategoryRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityProductCategoryRelationshipColumns.RelationshipID+" DESC"))
					mods = append(mods, model.PromotionActivityProductCategoryRelationshipWhere.RelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityProductCategoryRelationshipColumns.RelationshipID+" ASC"))
					mods = append(mods, model.PromotionActivityProductCategoryRelationshipWhere.RelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityProductCategoryRelationshipColumns.RelationshipID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductCategoryRelationshipColumns.RelationshipID, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductCategoryRelationshipColumns.ActivityID, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.ActivityType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductCategoryRelationshipColumns.ActivityType, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.ProductCategoryID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductCategoryRelationshipColumns.ProductCategoryID, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.Sort:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductCategoryRelationshipColumns.Sort, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityProductCategoryRelationshipColumns.Status, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.CreatedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityProductCategoryRelationshipColumns.CreatedAt, opMap)...)
		case model.PromotionActivityProductCategoryRelationshipColumns.UpdatedAt:
			mods = append(mods, modelx.GetTimeMods(model.PromotionActivityProductCategoryRelationshipColumns.UpdatedAt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivityProductCategoryRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.PromotionActivityProductCategoryRelationshipColumns.RelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivityProductCategoryRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetCouponList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivityCouponRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityCouponRelationshipColumns.RelationshipID+" DESC"))
					mods = append(mods, model.PromotionActivityCouponRelationshipWhere.RelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityCouponRelationshipColumns.RelationshipID+" ASC"))
					mods = append(mods, model.PromotionActivityCouponRelationshipWhere.RelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "orderBy":
			if withCount != 3 && withCount != 4 {
				if val, ok := v.(string); ok && val != "" {
					mods = append(mods, qm.OrderBy(val))
				}
			}
		case "select":
			if val, ok := v.(string); ok && val != "" {
				selectCol = val
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityCouponRelationshipColumns.RelationshipID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.RelationshipID, opMap)...)
		case model.PromotionActivityCouponRelationshipColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.ActivityID, opMap)...)
		case model.PromotionActivityCouponRelationshipColumns.ActivityType:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.ActivityType, opMap)...)
		case model.PromotionActivityCouponRelationshipColumns.CouponID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.CouponID, opMap)...)
		case model.PromotionActivityCouponRelationshipColumns.PerLimit:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.PerLimit, opMap)...)
		case model.PromotionActivityCouponRelationshipColumns.Sort:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.Sort, opMap)...)
		case model.PromotionActivityCouponRelationshipColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityCouponRelationshipColumns.Status, opMap)...)

		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivityCouponRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}

		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	} else {
		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	}

	var columns []string
	if selectCol != "" {
		if selectCol != "," {
			columns = strings.Split(selectCol, ",")
		} else {
			columns = append(columns, model.PromotionActivityCouponRelationshipColumns.RelationshipID)
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivityCouponRelationships(mods...).All(ctx, r.mysqlConn)
	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetLogList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivityLog, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityLogColumns.LogID+" DESC"))
					mods = append(mods, model.PromotionActivityLogWhere.LogID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityLogColumns.LogID+" ASC"))
					mods = append(mods, model.PromotionActivityLogWhere.LogID.GT(val))
					previousCount = 1
				}
			}
		case "orderBy":
			if withCount != 3 && withCount != 4 {
				if val, ok := v.(string); ok && val != "" {
					mods = append(mods, qm.OrderBy(val))
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && val != "" {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityLogColumns.LogID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityLogColumns.LogID, opMap)...)
		case model.PromotionActivityLogColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityLogColumns.ActivityID, opMap)...)
		case model.PromotionActivityLogColumns.UserID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityLogColumns.UserID, opMap)...)
		case model.PromotionActivityLogColumns.OrderID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityLogColumns.OrderID, opMap)...)
		case model.PromotionActivityLogColumns.Type:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityLogColumns.Type, opMap)...)
		case model.PromotionActivityLogColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityLogColumns.Status, opMap)...)
		}
	}

	if withCount >= 2 {
		if withCount == 5 { // 统计参与次数
			mods = append(mods, qm.Select(fmt.Sprintf(
				"%s, count(%s) as %s",
				model.PromotionActivityLogColumns.ActivityID,
				model.PromotionActivityLogColumns.OrderID,
				model.PromotionActivityLogColumns.OrderID,
			)))
			mods = append(mods, qm.GroupBy(model.PromotionActivityLogColumns.ActivityID))
		}

		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivityLogs(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}

		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	} else {
		if pageSize > 0 {
			if page > 1 {
				mods = append(mods, qm.Offset(pageSize*(page-1)))
			}
			mods = append(mods, qm.Limit(pageSize))
		}
	}

	var columns []string
	if selectCol != "" {
		if selectCol != "," {
			columns = strings.Split(selectCol, ",")
		} else {
			columns = append(columns, model.PromotionActivityLogColumns.LogID)
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivityLogs(mods...).All(ctx, r.mysqlConn)
	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) UpdateBindRel(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
	rel *model.PromotionActivityBindRel,
) error {
	if rel == nil {
		return nil
	}

	var db boil.ContextExecutor
	if tx != nil {
		db = tx
	} else {
		db = r.mysqlConn
	}

	if len(rel.Products) > 0 {
		for _, relationShip := range rel.Products {
			relationShip.ActivityID = id
			err := relationShip.Insert(ctx, db, boil.Infer())
			if err != nil {
				return err
			}
		}
	}

	if len(rel.DelSkuIds) > 0 {
		var mods []qm.QueryMod
		mods = append(mods, model.PromotionActivityProductRelationshipWhere.ActivityID.EQ(id))
		mods = append(mods, model.PromotionActivityProductRelationshipWhere.SkuID.IN(rel.DelSkuIds))
		_, err := model.PromotionActivityProductRelationships(mods...).DeleteAll(ctx, db)
		if err != nil {
			return err
		}
	}

	if len(rel.Brands) > 0 {
		for _, relationShip := range rel.Brands {
			relationShip.ActivityID = id
			err := relationShip.Insert(ctx, db, boil.Infer())
			if err != nil {
				return err
			}
		}
	}

	if len(rel.DelBrandIds) > 0 {
		var mods []qm.QueryMod
		mods = append(mods, model.PromotionActivityProductBrandRelationshipWhere.ActivityID.EQ(id))
		mods = append(mods, model.PromotionActivityProductBrandRelationshipWhere.ProductBrandID.IN(rel.DelBrandIds))
		_, err := model.PromotionActivityProductBrandRelationships(mods...).DeleteAll(ctx, db)
		if err != nil {
			return err
		}
	}

	if len(rel.Categories) > 0 {
		for _, relationShip := range rel.Categories {
			relationShip.ActivityID = id
			err := relationShip.Insert(ctx, db, boil.Infer())
			if err != nil {
				return err
			}
		}
	}

	if len(rel.DelCategoryIds) > 0 {
		var mods []qm.QueryMod
		mods = append(mods, model.PromotionActivityProductCategoryRelationshipWhere.ActivityID.EQ(id))
		mods = append(mods, model.PromotionActivityProductCategoryRelationshipWhere.ProductCategoryID.IN(rel.DelCategoryIds))
		_, err := model.PromotionActivityProductCategoryRelationships(mods...).DeleteAll(ctx, db)
		if err != nil {
			return err
		}
	}

	if len(rel.Coupons) > 0 {
		for _, relationShip := range rel.Coupons {
			relationShip.ActivityID = id
			err := relationShip.Insert(ctx, db, boil.Infer())
			if err != nil {
				return err
			}
		}
	}

	if len(rel.DelCouponIds) > 0 {
		var mods []qm.QueryMod
		mods = append(mods, model.PromotionActivityCouponRelationshipWhere.ActivityID.EQ(id))
		mods = append(mods, model.PromotionActivityCouponRelationshipWhere.CouponID.IN(rel.DelCouponIds))
		_, err := model.PromotionActivityCouponRelationships(mods...).DeleteAll(ctx, db)
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *customActivityRepository) SyncQiniu(ctx context.Context, id uint64, mediaId uint64, url string) (rowsAff int64, err error) {
	var mods []qm.QueryMod
	mods = append(mods, model.PromotionAttachmentRelationshipWhere.ObjectID.EQ(id))
	mods = append(mods, model.PromotionAttachmentRelationshipWhere.AttachmentID.EQ(mediaId))
	list, err := model.PromotionAttachmentRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if len(list) == 0 {
		return
	}

	urlStr := url + "?" + strconv.FormatUint(mediaId, 10)

	for _, item := range list {
		if len(item.AttachmentSource) == 0 {
			continue
		}

		var subMods []qm.QueryMod
		var metaMods []qm.QueryMod
		switch int32(item.ObjectType) {
		case globalkey.AttachmentLogTypePromotion:
			subMods = append(subMods, model.PromotionActivityWhere.ID.EQ(item.ObjectID))
			subList, subErr := model.PromotionActivities(subMods...).All(ctx, r.mysqlConn)
			if subErr != nil {
				logx.Errorw("SyncQiniu PromotionActivity error", logx.Field("detail", subErr.Error()))
				logrus.Info(fmt.Sprintf("SyncQiniu PromotionActivity error, activityId: %d, err: %+v", item.ObjectID, subErr))
				continue
			}

			for _, subItem := range subList {
				subItem.Description = strings.Replace(subItem.Description, item.AttachmentSource, urlStr, -1)
				subItem.DescriptionFiltered = strings.Replace(subItem.DescriptionFiltered, item.AttachmentSource, urlStr, -1)
				_, subErr = subItem.Update(ctx, r.mysqlConn, boil.Whitelist(
					model.PromotionActivityColumns.Description,
					model.PromotionActivityColumns.DescriptionFiltered,
				))
				if subErr != nil {
					logx.Errorw("SyncQiniu PromotionActivity update error", logx.Field("detail", subErr.Error()))
					logrus.Info(fmt.Sprintf("SyncQiniu PromotionActivity update error, activityId: %d, err: %+v", item.ObjectID, subErr))
				}
			}

			metaMods = append(metaMods, model.PromotionActivityMetumWhere.ActivityID.EQ(item.ObjectID))
			metaMods = append(metaMods, model.PromotionActivityMetumWhere.MetaKey.EQ("_thumbnail_url"))
			metaList, err := model.PromotionActivityMeta(metaMods...).All(ctx, r.mysqlConn)
			if err != nil {
				logx.Errorw("SyncQiniu PromotionActivityMetum error", logx.Field("detail", err.Error()))
				logrus.Info(fmt.Sprintf("SyncQiniu PromotionActivityMetum error, activityId: %d, err: %+v", item.ObjectID, err))
				continue
			}

			for _, metum := range metaList {
				metum.MetaValue = null.StringFrom(url)
				_, err = metum.Update(ctx, r.mysqlConn, boil.Whitelist(
					model.PromotionActivityMetumColumns.MetaValue,
				))
				if err != nil {
					logx.Errorw("SyncQiniu PromotionActivityMetum update error", logx.Field("detail", err.Error()))
					logrus.Info(fmt.Sprintf("SyncQiniu PromotionActivityMetum update error, activityId: %d, err: %+v", item.ObjectID, err))
				}
			}
		case globalkey.AttachmentLogTypePromotionCoupon:
			subMods = append(subMods, model.PromotionCouponTemplateWhere.ID.EQ(item.ObjectID))
			subList, subErr := model.PromotionCouponTemplates(subMods...).All(ctx, r.mysqlConn)
			if subErr != nil {
				logx.Errorw("SyncQiniu PromotionCouponTemplate error", logx.Field("detail", subErr.Error()))
				logrus.Info(fmt.Sprintf("SyncQiniu PromotionCouponTemplate error, templateId: %d, err: %+v", item.ObjectID, subErr))
				continue
			}

			for _, subItem := range subList {
				subItem.Description = strings.Replace(subItem.Description, item.AttachmentSource, urlStr, -1)
				subItem.DescriptionFiltered = strings.Replace(subItem.DescriptionFiltered, item.AttachmentSource, urlStr, -1)
				_, subErr = subItem.Update(ctx, r.mysqlConn, boil.Whitelist(
					model.PromotionCouponTemplateColumns.Description,
					model.PromotionCouponTemplateColumns.DescriptionFiltered,
				))
				if subErr != nil {
					logx.Errorw("SyncQiniu PromotionCouponTemplate update error", logx.Field("detail", subErr.Error()))
					logrus.Info(fmt.Sprintf("SyncQiniu PromotionCouponTemplate update error, templateId: %d, err: %+v", item.ObjectID, subErr))
				}
			}

			metaMods = append(metaMods, model.PromotionActivityMetumWhere.ActivityID.EQ(item.ObjectID))
			metaMods = append(metaMods, model.PromotionActivityMetumWhere.MetaKey.EQ("_thumbnail_url"))
			metaList, err := model.PromotionCouponMeta(metaMods...).All(ctx, r.mysqlConn)
			if err != nil {
				logx.Errorw("SyncQiniu PromotionActivityMetum error", logx.Field("detail", err.Error()))
				logrus.Info(fmt.Sprintf("SyncQiniu PromotionActivityMetum error, templateId: %d, err: %+v", item.ObjectID, err))
				continue
			}

			for _, metum := range metaList {
				metum.MetaValue = null.StringFrom(url)
				_, err = metum.Update(ctx, r.mysqlConn, boil.Whitelist(
					model.PromotionActivityMetumColumns.MetaValue,
				))
				if err != nil {
					logx.Errorw("SyncQiniu PromotionActivityMetum update error", logx.Field("detail", err.Error()))
					logrus.Info(fmt.Sprintf("SyncQiniu PromotionActivityMetum update error, templateId: %d, err: %+v", item.ObjectID, err))
				}
			}
		}
	}

	rowsAff, err = model.PromotionAttachmentRelationships(mods...).UpdateAll(ctx, r.mysqlConn, model.M{
		model.PromotionAttachmentRelationshipColumns.AttachmentImageURL: url,
	})

	return
}

func (r *customActivityRepository) GetMedia(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionAttachmentRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionAttachmentRelationshipColumns.AttachmentRelationshipID+" DESC"))
					mods = append(mods, model.PromotionAttachmentRelationshipWhere.AttachmentRelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionAttachmentRelationshipColumns.AttachmentRelationshipID+" ASC"))
					mods = append(mods, model.PromotionAttachmentRelationshipWhere.AttachmentRelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionAttachmentRelationshipColumns.AttachmentRelationshipID:
			mods = append(mods, modelx.GetIntMods(model.PromotionAttachmentRelationshipColumns.AttachmentRelationshipID, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.ObjectID:
			mods = append(mods, modelx.GetIntMods(model.PromotionAttachmentRelationshipColumns.ObjectID, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.ObjectType:
			mods = append(mods, modelx.GetIntMods(model.PromotionAttachmentRelationshipColumns.ObjectType, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.AttachmentID:
			mods = append(mods, modelx.GetIntMods(model.PromotionAttachmentRelationshipColumns.AttachmentID, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.AttachmentThumbnail:
			mods = append(mods, modelx.GetIntMods(model.PromotionAttachmentRelationshipColumns.AttachmentThumbnail, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.AttachmentOrder:
			mods = append(mods, modelx.GetIntMods(model.PromotionAttachmentRelationshipColumns.AttachmentOrder, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.AttachmentSource:
			mods = append(mods, modelx.GetStringMods(model.PromotionAttachmentRelationshipColumns.AttachmentSource, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.AttachmentImageURL:
			mods = append(mods, modelx.GetStringMods(model.PromotionAttachmentRelationshipColumns.AttachmentImageURL, opMap)...)
		case model.PromotionAttachmentRelationshipColumns.AttachmentImageAlt:
			mods = append(mods, modelx.GetStringMods(model.PromotionAttachmentRelationshipColumns.AttachmentImageAlt, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionAttachmentRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.PromotionAttachmentRelationshipColumns.AttachmentRelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionAttachmentRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customActivityRepository) GetMeta(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.PromotionActivityMetum, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityMetumColumns.MetaID+" DESC"))
					mods = append(mods, model.PromotionActivityMetumWhere.MetaID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.PromotionActivityMetumColumns.MetaID+" ASC"))
					mods = append(mods, model.PromotionActivityMetumWhere.MetaID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.PromotionActivityMetumColumns.MetaID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityMetumColumns.MetaID, opMap)...)
		case model.PromotionActivityMetumColumns.ActivityID:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityMetumColumns.ActivityID, opMap)...)
		case model.PromotionActivityMetumColumns.MetaKey:
			mods = append(mods, modelx.GetStringMods(model.PromotionActivityMetumColumns.MetaKey, opMap)...)
		case model.PromotionActivityMetumColumns.MetaValue:
			mods = append(mods, modelx.GetIntMods(model.PromotionActivityMetumColumns.MetaValue, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.PromotionActivityMeta(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.PromotionActivityMetumColumns.MetaID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.PromotionActivityMeta(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}
